
//! 声明式(规则)宏，编译阶段会替换用宏的地方， 声明宏可以在任何地方进行声明，在使用的地方use
//! 过程宏实在语言的发展过程中产生的，提供更具体的控制和功能，所以需要在编译使用项目之前确定宏先编译好，
//!    所以它都是在单独的一个项目中， 参考macro_study_derive
//! item：比如一个函数、结构体、模块等
//! block：代码块。比如一系列由花括号包裹的表达式和语句
//! stmt：语句。比如一个赋值语句
//! pat：模式
//! expr：表达式。（前面例子使用过了）
//! ty：类型。比如 Vec
//! ident：标识符。比如一个变量名
//! path：路径。比如：foo、::std::mem::replace、transmute::<_, int>
//! meta：元数据。一般是在 #[...] 和 #![...] 属性内部的数据
//! tt：单个的 token 树
//! vis：可能为空的一个 Visibility 修饰符。比如 pub、pub(crate)
//!  $(...)* 或 $(...)+ 结构是一种重复模式

/// 这是一个结构体，实现了HelloMacro trait的，
/// 后面会实现一个派生宏，来自动实现HalloMacro
#[macro_export]
macro_rules! say_hello {
    () => {
        println!("hello");
    };

    (
        [$($attrs_pub:tt)*]
        struct $name:ident $($rest:tt)*
    ) => {
        println!("hello2222");
    };

    ($($t:tt)*) => {
        println!("hello44444");
    };
}

#[macro_export]
macro_rules! say_hello1 {
    ($x:ident) => { // 能匹配一个标识符
        println!("hello.{} this is a ident", stringify!($x) );
    };

    ($x:expr) => {// 匹配表达式
        println!("hello.{} this is a expr", stringify!($x));
    };

    ($($x:expr),*) => {// 匹配多个表达式，$()表示组，*，表示有0个到多个的前面组的表达式
        println!("hello.{} this is a mutiparty expr", stringify!($x));
    };

    ($x:ty) => {// 匹配类型
        println!("hello.{} this is a type", stringify!($x));
    };


}

#[macro_export]
macro_rules! foo {
    ($x:ident) => {
        println!("This is an identifier: {}", $x);
    };
    ($x:ty) => {
        println!("This is a type: {}", stringify!($x));
    };
}